﻿// 2023/3/8: 首个版本
// 2023/6/7: 修复安装插件后搜索崩溃问题
// 2023/9/22: 使用PassParent给ShowDialog传参
// 2023/9/25: 改为直接输入Icon对象

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using ASEva;
using ASEva.Samples;
using ASEva.Utility;
using ASEva.UIEto;
using Eto.Forms;
using Eto.Drawing;

namespace CommonSource
{
    class PluginLibraryDialog : DialogPanel
    {
        public PluginLibraryDialog(Icon icon = null)
        {
            Icon = icon;
            Title = t["title"];
            SetResizableMode(910, 610, 910, 610);

            var mainLayout = this.SetContentAsRowLayout(8, 8, VerticalAlignment.Stretch);
            var leftLayout = mainLayout.AddColumnLayout(false, 300, 0, 8);
            var rightLayout = mainLayout.AddColumnLayout(true);

            var searchBox = leftLayout.AddControl(new SearchBox()) as SearchBox;
            var listBox = leftLayout.AddControl(new ListBox(), true) as ListBox;
            var enableDisableLayout = leftLayout.AddRowLayout();
            var buttonEnableAll = enableDisableLayout.AddButton(t["enable-all-plugins"], true);
            var buttonDisableAll = enableDisableLayout.AddButton(t["disable-all-plugins"], true);
            var buttonInstall = leftLayout.AddButton(t["install-plugin"]);

            var topLayout = rightLayout.AddRowLayout();
            var groupLayout = rightLayout.AddGroupBox(t["information"], true).SetContentAsColumnLayout();

            var checkEnabled = topLayout.AddCheckBox("-");
            checkEnabled.SetLogicalWidth(200);
            checkEnabled.Enabled = false;
            topLayout.AddSpace();
            var buttonUninstall = topLayout.AddButton(t["uninstall"], false, 120);
            buttonUninstall.Enabled = false;

            var basicLayout = groupLayout.AddTableLayout();
            var briefLayout = groupLayout.AddColumnLayout(false, 0, 100, 2);
            var appLayout = groupLayout.AddColumnLayout(true, 2);
            var nativeLayout = groupLayout.AddColumnLayout(true, 2);

            var row = basicLayout.AddRow();
            row.AddLabel("ID:", TextAlignment.Left);
            var labelID = row.AddLabel("-", true);
            row = basicLayout.AddRow();
            row.AddLabel(t["version"], TextAlignment.Left);
            var labelVersion = row.AddLabel("-", true);

            briefLayout.AddLabel(t["brief"], TextAlignment.Left);
            var textBrief = briefLayout.AddControl(new TextArea{ ReadOnly = true, Text = t["none"] }, true) as TextArea;

            appLayout.AddLabel(t["application-layer"], TextAlignment.Left);
            var textAppLayer = appLayout.AddControl(new TextArea{ ReadOnly = true }, true) as TextArea;

            nativeLayout.AddLabel(t["native-layer"], TextAlignment.Left);
            var textNativeLayer = nativeLayout.AddControl(new TextArea{ ReadOnly = true }, true) as TextArea;

            foreach (var id in Agency.GetPluginPackIDList())
            {
                var pack = Agency.GetPluginPackInfo(id);
                allItems.Add(new PackItem
                {
                    ID = id,
                    Name = pack.Name,
                });
            }
            allItems.Sort();

            updateVisibleItems(null, listBox);

            listBox.SelectedIndexChanged += delegate
            {
                updatingCheckEnabled = true;

                PackItem item = null;
                PluginPackInfo pack = null;
                if (listBox.SelectedIndex >= 0)
                {
                    item = visibleItems[listBox.SelectedIndex];
                    pack = Agency.GetPluginPackInfo(item.ID);
                }

                if (pack == null)
                {
                    checkEnabled.Enabled = false;
                    checkEnabled.Text = "-";
                    buttonUninstall.Enabled = false;
                    labelID.Text = labelVersion.Text = "-";
                    textBrief.Text = t["none"];
                    textAppLayer.Text = textNativeLayer.Text = "";
                }
                else
                {
                    checkEnabled.Enabled = true;
                    updateCheckEnable(checkEnabled, pack.Status);
                    buttonUninstall.Enabled = true;
                    labelID.Text = item.ID;
                    labelVersion.Text = pack.Version.ToString(3);
                    textBrief.Text = pack.Brief;
                    textAppLayer.Text = pack.AppLayerDetails;
                    textNativeLayer.Text = pack.NativeLayerDetails;
                }
                
                updatingCheckEnabled = false;
            };

            buttonUninstall.Click += delegate
            {
                if (listBox.SelectedIndex < 0) return;

                var item = visibleItems[listBox.SelectedIndex];
                if (!Agency.PopupConfirm(t.Format("confirm-uninstall", item.Name))) return;

                if (Agency.UninstallPlugin(item.ID))
                {
                    visibleItems.Remove(item);
                    allItems.Remove(item);
                    listBox.Items.RemoveAt(listBox.SelectedIndex);
                    Modified = true;
                }
            };

            buttonInstall.Click += delegate
            {
                var dialog = new SelectFolderDialog();
                dialog.Title = t["install-title"];
                if (dialog.ShowDialog(App.PassParent(this)) == DialogResult.Ok)
                {
                    if (Agency.InstallPlugin(dialog.Directory))
                    {
                        var itemsToRemove = new List<PackItem>();
                        foreach (var item in allItems)
                        {
                            if (Agency.GetPluginPackInfo(item.ID) == null) itemsToRemove.Add(item);
                        }
                        foreach (var item in itemsToRemove)
                        {
                            var itemIndex = visibleItems.IndexOf(item);
                            if (itemIndex >= 0) listBox.Items.RemoveAt(itemIndex);
                            visibleItems.Remove(item);
                            allItems.Remove(item);
                        }
                        Modified = true;
                    }
                }
            };

            checkEnabled.CheckedChanged += delegate
            {
                if (updatingCheckEnabled) return;
                if (listBox.SelectedIndex < 0) return;

                var item = visibleItems[listBox.SelectedIndex];

                var pluginInfo = Agency.GetPluginPackInfo(item.ID);
                if (checkEnabled.Checked.Value)
                {
                    if (pluginInfo.Status != PluginPackStatus.Disabled) return;
                    Agency.EnablePlugin(item.ID);
                }
                else
                {
                    if (pluginInfo.Status == PluginPackStatus.Disabled) return;
                    Agency.DisablePlugin(item.ID);
                }
                Modified = true;

                pluginInfo = Agency.GetPluginPackInfo(item.ID);
                updateCheckEnable(checkEnabled, pluginInfo.Status);
            };

            searchBox.TextChanged += delegate
            {
                updateVisibleItems(searchBox.Text, listBox);
                buttonEnableAll.Enabled = buttonDisableAll.Enabled = searchBox.Text.Length == 0;
            };

            buttonDisableAll.Click += delegate
            {
                if (!Agency.PopupConfirm(t["confirm-disable"])) return;
                Agency.DisableAllPlugins();
                updateVisibleItems(searchBox.Text, listBox);
                Modified = true;
            };

            buttonEnableAll.Click += delegate
            {
                if (!Agency.PopupConfirm(t["confirm-enable"])) return;
                foreach (var packID in Agency.GetPluginPackIDList())
                {
                    Agency.EnablePlugin(packID);
                }
                updateVisibleItems(searchBox.Text, listBox);
                Agency.PopupNotice(t["restart-notice"]);
            };
        }

        public bool Modified { get; set; }

        private void updateCheckEnable(CheckBox checkEnable, PluginPackStatus status)
        {
            switch (status)
            {
                case PluginPackStatus.Disabled:
                    checkEnable.Checked = false;
                    checkEnable.Text = t["disabled"];;
                    break;
                case PluginPackStatus.Enabled:
                    checkEnable.Checked = true;
                    checkEnable.Text = t["enabled"];
                    break;
                case PluginPackStatus.ToBeEnabled:
                    checkEnable.Checked = true;
                    checkEnable.Text = t["to-be-enabled"];
                    break;
            }
        }

        private void updateVisibleItems(String key, ListBox listBox)
        {
            key = key == null ? null : key.ToLower();

            visibleItems.Clear();
            if (String.IsNullOrEmpty(key))
            {
                visibleItems.AddRange(allItems);
            }
            else
            {
                foreach (var item in allItems)
                {
                    if (item.ID.ToLower().Contains(key) || item.Name.ToLower().Contains(key))
                    {
                        visibleItems.Add(item);
                        continue;
                    }
                    var pack = Agency.GetPluginPackInfo(item.ID);
                    if (pack.Version.ToString().Contains(key) || pack.Brief.ToLower().Contains(key) || pack.AppLayerDetails.ToLower().Contains(key) || pack.NativeLayerDetails.ToLower().Contains(key))
                    {
                        visibleItems.Add(item);
                        continue;
                    }
                }
            }

            listBox.Items.Clear();
            foreach (var item in visibleItems)
            {
                var pack = Agency.GetPluginPackInfo(item.ID);

                String errorText = "";
                switch (pack.Error)
                {
                    case PluginPackError.Disabled:
                        errorText = t["disabled"];
                        break;
                    case PluginPackError.LoadFailed:
                        errorText = t["load-failed"];
                        break;
                    case PluginPackError.Unlicensed:
                        errorText = t["unlicensed"];
                        break;
                    case PluginPackError.PlatformUnsupported:
                        errorText = t["platform-unsupported"];
                        break;
                }
                if (errorText.Length > 0) errorText = " (" + errorText + ")";

                listBox.Items.Add(item.Name + errorText);
            }
        }

        private class PackItem : IComparable
        {
            public String ID { get; set; }
            public String Name { get; set; }

            public int CompareTo(object obj)
            {
                return Name.CompareTo((obj as PackItem).Name);
            }

            public override string ToString()
            {
                return Name;
            }
        }

        private List<PackItem> allItems = new List<PackItem>();
        private List<PackItem> visibleItems = new List<PackItem>();
        private bool updatingCheckEnabled = false;

        private TextResource t = TextResource.Load(Convert.FromBase64String("PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHRleHRfcmVzb3VyY2U+CiAgPHQgaWQ9ImFwcGxpY2F0aW9uLWxheWVyIj4KICAgIDxlbj5BcHBsaWNhdGlvbiBsYXllcjo8L2VuPgogICAgPGNoPuW6lOeUqOWxgjo8L2NoPgogIDwvdD4KICA8dCBpZD0iYnJpZWYiPgogICAgPGVuPkJyaWVmOjwvZW4+CiAgICA8Y2g+566A5LuLOjwvY2g+CiAgPC90PgogIDx0IGlkPSJjb25maXJtLWRpc2FibGUiPgogICAgPGVuPkFyZSB5b3Ugc3VyZSB0byBkaXNhYmxlIGFsbCBwbHVnaW5zPzwvZW4+CiAgICA8Y2g+56Gu6K6k5piv5ZCm56aB55So5omA5pyJ5o+S5Lu2PzwvY2g+CiAgPC90PgogIDx0IGlkPSJjb25maXJtLWVuYWJsZSI+CiAgICA8ZW4+QXJlIHlvdSBzdXJlIHRvIGVuYWJsZSBhbGwgcGx1Z2lucz88L2VuPgogICAgPGNoPuehruiupOaYr+WQpuWQr+eUqOaJgOacieaPkuS7tj88L2NoPgogIDwvdD4KICA8dCBpZD0iY29uZmlybS11bmluc3RhbGwiPgogICAgPGVuPkFyZSB5b3Ugc3VyZSB0byB1bmluc3RhbGwgcGx1Z2luJ3swfSc/PC9lbj4KICAgIDxjaD7noa7orqTmmK/lkKbljbjovb3mj5Lku7YnezB9Jz88L2NoPgogIDwvdD4KICA8dCBpZD0iZGlzYWJsZS1hbGwtcGx1Z2lucyI+CiAgICA8ZW4+RGlzYWJsZSBhbGwgcGx1Z2luczwvZW4+CiAgICA8Y2g+56aB55So5YWo6YOo5o+S5Lu2PC9jaD4KICA8L3Q+CiAgPHQgaWQ9ImRpc2FibGVkIj4KICAgIDxlbj5EaXNhYmxlZDwvZW4+CiAgICA8Y2g+5bey56aB55SoPC9jaD4KICA8L3Q+CiAgPHQgaWQ9ImVuYWJsZS1hbGwtcGx1Z2lucyI+CiAgICA8ZW4+RW5hYmxlIGFsbCBwbHVnaW5zPC9lbj4KICAgIDxjaD7lkK/nlKjlhajpg6jmj5Lku7Y8L2NoPgogIDwvdD4KICA8dCBpZD0iZW5hYmxlZCI+CiAgICA8ZW4+RW5hYmxlZDwvZW4+CiAgICA8Y2g+5bey5ZCv55SoPC9jaD4KICA8L3Q+CiAgPHQgaWQ9ImluZm9ybWF0aW9uIj4KICAgIDxlbj5JbmZvcm1hdGlvbjwvZW4+CiAgICA8Y2g+5o+S5Lu25L+h5oGvPC9jaD4KICA8L3Q+CiAgPHQgaWQ9Imluc3RhbGwtcGx1Z2luIj4KICAgIDxlbj5JbnN0YWxsIHBsdWdpbjwvZW4+CiAgICA8Y2g+5a6J6KOFPC9jaD4KICA8L3Q+CiAgPHQgaWQ9Imluc3RhbGwtdGl0bGUiPgogICAgPGVuPlBsZWFzZSBzZWxlY3QgdGhlIGZvbGRlciBjb250YWluaW5nIHBsdWdpbihzKS48L2VuPgogICAgPGNoPumAieaLqeWMheWQq+aPkuS7tueahOaWh+S7tuWkuTwvY2g+CiAgPC90PgogIDx0IGlkPSJsb2FkLWZhaWxlZCI+CiAgICA8ZW4+TG9hZCBmYWlsZWQ8L2VuPgogICAgPGNoPuWKoOi9veWksei0pTwvY2g+CiAgPC90PgogIDx0IGlkPSJuYXRpdmUtbGF5ZXIiPgogICAgPGVuPk5hdGl2ZSBsYXllcjo8L2VuPgogICAgPGNoPuWOn+eUn+Wxgjo8L2NoPgogIDwvdD4KICA8dCBpZD0ibm9uZSI+CiAgICA8ZW4+KE5vbmUpPC9lbj4KICAgIDxjaD4o5peg5L+h5oGvKTwvY2g+CiAgPC90PgogIDx0IGlkPSJwbGF0Zm9ybS11bnN1cHBvcnRlZCI+CiAgICA8ZW4+VUkgdW5zdXBwb3J0ZWQ8L2VuPgogICAgPGNoPlVJ5LiN5pSv5oyBPC9jaD4KICA8L3Q+CiAgPHQgaWQ9InJlc3RhcnQtbm90aWNlIj4KICAgIDxlbj5QbGVhc2UgcmVzdGFydCBzb2Z0d2FyZSB0byBhY3RpdmF0ZSB0aGUgZW5hYmxlZCBwbHVnaW5zLjwvZW4+CiAgICA8Y2g+6K+36YeN5ZCv6L2v5Lu25Lul5r+A5rS75ZCv55So55qE5o+S5Lu244CCPC9jaD4KICA8L3Q+CiAgPHQgaWQ9InRpdGxlIj4KICAgIDxlbj5QbHVnaW4gTGlicmFyeTwvZW4+CiAgICA8Y2g+5o+S5Lu2566h55CGPC9jaD4KICA8L3Q+CiAgPHQgaWQ9InRvLWJlLWVuYWJsZWQiPgogICAgPGVuPlRvIGJlIGVuYWJsZWQ8L2VuPgogICAgPGNoPuS4i+asoeWQr+eUqDwvY2g+CiAgPC90PgogIDx0IGlkPSJ1bmluc3RhbGwiPgogICAgPGVuPlVuaW5zdGFsbDwvZW4+CiAgICA8Y2g+5Y246L29PC9jaD4KICA8L3Q+CiAgPHQgaWQ9InVubGljZW5zZWQiPgogICAgPGVuPlVubGljZW5zZWQ8L2VuPgogICAgPGNoPuacquiuuOWPrzwvY2g+CiAgPC90PgogIDx0IGlkPSJ2ZXJzaW9uIj4KICAgIDxlbj5WZXJzaW9uOjwvZW4+CiAgICA8Y2g+54mI5pysOjwvY2g+CiAgPC90Pgo8L3RleHRfcmVzb3VyY2U+"), null);
    }
}
